package com.aizuda.boot.modules.business.contractNumber.service.impl;

import com.aizuda.boot.modules.business.contract.dto.UserInfo;
import com.aizuda.boot.modules.business.contract.util.AuthUtil;
import com.aizuda.boot.modules.business.contractNumber.domain.entity.ContractNumberRuleComponentEntity;
import com.aizuda.boot.modules.business.contractNumber.domain.entity.ContractNumberRuleEntity;
import com.aizuda.boot.modules.business.contractNumber.domain.entity.ContractNumberSequenceEntity;
import com.aizuda.boot.modules.business.contractNumber.domain.response.ComponentVO;
import com.aizuda.boot.modules.business.contractNumber.domain.response.ContractNumberRuleDetailVO;
import com.aizuda.boot.modules.business.contractNumber.domain.response.ContractNumberRuleListVO;
import com.aizuda.boot.modules.business.contractNumber.domain.resquest.Component;
import com.aizuda.boot.modules.business.contractNumber.domain.resquest.ContractNumberRuleSaveDTO;
import com.aizuda.boot.modules.business.contractNumber.domain.resquest.GenerateNumberDTO;
import com.aizuda.boot.modules.common.constant.RedisKeyConstant;
import com.aizuda.boot.modules.common.constant.enums.ComponentTypeEnums;
import com.aizuda.boot.modules.common.constant.enums.NumberModeEnums;
import com.aizuda.boot.modules.common.constant.enums.RuleTypeEnums;
import com.aizuda.boot.modules.common.constant.enums.SequenceResetEnums;
import com.aizuda.boot.modules.common.constant.enums.SubjectAddModeEnums;
import com.aizuda.boot.modules.business.contractNumber.mapper.ContractNumberRuleMapper;
import com.aizuda.boot.modules.business.contractNumber.service.ContractNumberRuleComponentService;
import com.aizuda.boot.modules.business.contractNumber.service.ContractNumberRuleService;
import com.aizuda.boot.modules.business.contractNumber.service.ContractNumberSequenceService;
import com.aizuda.boot.modules.business.counterparty.entity.LegalEntityDetailEntity;
import com.aizuda.boot.modules.business.counterparty.service.LegalEntityService;
import com.aizuda.boot.modules.business.performance.mapper.ContractTypeMapper;
import com.aizuda.core.api.ApiAssert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.types.Expiration;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

import lombok.extern.slf4j.Slf4j;
import com.aizuda.boot.modules.business.contract.entity.ContractTypeEntity;

/**
 * @Author sangyirong
 * @ClassName ContractNumberRuleServiceImpl
 * @Version 1.0
 * @Date 2025/7/2 16:24
 */
@Slf4j
@Service
public class ContractNumberRuleServiceImpl extends ServiceImpl<ContractNumberRuleMapper, ContractNumberRuleEntity> implements ContractNumberRuleService {

    /**
     * 生成上下文，用于跟踪生成过程中的状态
     */
    private static class GenerationContext {
        private int ourPartyOccurrenceCount = 0; // 我方主体出现次数计数器
        private boolean ourPartyAdded = false; // 是否已添加我方主体（用于FIRST_ONLY模式）

        public int getOurPartyOccurrenceCount() {
            return ourPartyOccurrenceCount;
        }

        public void incrementOurPartyOccurrence() {
            this.ourPartyOccurrenceCount++;
        }

        public boolean isOurPartyAdded() {
            return ourPartyAdded;
        }

        public void setOurPartyAdded(boolean ourPartyAdded) {
            this.ourPartyAdded = ourPartyAdded;
        }

        public void reset() {
            this.ourPartyOccurrenceCount = 0;
            this.ourPartyAdded = false;
        }
    }

    @Resource
    private ContractNumberRuleComponentService contractNumberRuleComponentService;

    @Resource
    private ContractNumberSequenceService contractNumberSequenceService;

    @Resource
    private LegalEntityService legalEntityService;

    @Resource
    private ContractTypeMapper contractTypeMapper;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    private static final ScheduledExecutorService LOCK_RENEW_POOL =
            new ScheduledThreadPoolExecutor(1, (r) -> {
                Thread t = new Thread(r, "lock-renew-thread");
                t.setDaemon(true);
                return t;
            });

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean create(ContractNumberRuleSaveDTO dto) {
        // 获取当前用户信息
        UserInfo currentUser = AuthUtil.getCurrentUser();
        ApiAssert.fail(Objects.isNull(currentUser.getEmployeeId()), "当前用户未登录，不允许创建!");

        // 参数校验
        ApiAssert.fail(Objects.isNull(dto), "合同编号规则数据不能为空");
        ApiAssert.fail(!StringUtils.hasText(dto.getRuleName()), "规则名称不能为空");
        ApiAssert.fail(!StringUtils.hasText(dto.getRuleCode()), "规则编码不能为空");
        ApiAssert.fail(Objects.isNull(dto.getRuleType()), "规则类型不能为空");
        ApiAssert.fail(Objects.isNull(dto.getGenerateTiming()), "生成时机不能为空");

        // 新增字段校验
        ApiAssert.fail(Objects.isNull(dto.getNumberMode()), "编号模式不能为空");
        ApiAssert.fail(Objects.isNull(dto.getSequenceReset()), "序号重置策略不能为空");
        ApiAssert.fail(Objects.isNull(dto.getSubjectAddMode()), "我方主体添加模式不能为空");

        // 检查规则名称是否重复
        long nameCount = this.count(new LambdaQueryWrapper<ContractNumberRuleEntity>()
                .eq(ContractNumberRuleEntity::getRuleName, dto.getRuleName()));
        ApiAssert.fail(nameCount > 0, "规则名称已存在");

        // 检查规则编码是否重复
        long codeCount = this.count(new LambdaQueryWrapper<ContractNumberRuleEntity>()
                .eq(ContractNumberRuleEntity::getRuleCode, dto.getRuleCode()));
        ApiAssert.fail(codeCount > 0, "规则编码已存在");

        // 创建合同编号规则主表数据
        ContractNumberRuleEntity ruleEntity = new ContractNumberRuleEntity();
        BeanUtils.copyProperties(dto, ruleEntity);
        ruleEntity.setCurrentSequence(0); // 初始序号为0
        if (Objects.isNull(dto.getIsEnabled())) {
            ruleEntity.setIsEnabled(true); // 默认启用
        }

        // 设置序号重置时间
        if (!SequenceResetEnums.NO_RESET.equals(dto.getSequenceReset())) {
            ruleEntity.setResetTime(new Date());
        }

        // 保存主表数据
        boolean saveResult = this.save(ruleEntity);
        ApiAssert.fail(!saveResult, "保存合同编号规则失败");

        // 保存规则组件数据
        if (!CollectionUtils.isEmpty(dto.getComponents())) {
            List<ContractNumberRuleComponentEntity> componentEntities = new ArrayList<>();
            int sortOrder = 1; // 排序值从1开始自动生成
            for (Component component : dto.getComponents()) {
                if (Objects.isNull(component.getComponentType())) {
                    continue; // 跳过组件类型为空的数据
                }

                // 如果是引用规则类型，验证引用的规则是否存在
                if (ComponentTypeEnums.RULE_REFERENCE.equals(component.getComponentType())
                        && StringUtils.hasText(component.getComponentValue())) {
                    try {
                        Long referencedRuleId = Long.parseLong(component.getComponentValue());
                        ContractNumberRuleEntity referencedRule = this.getById(referencedRuleId);
                        ApiAssert.fail(Objects.isNull(referencedRule), "引用的规则不存在，规则ID: " + referencedRuleId);

                        // 防止自己引用自己
                        ApiAssert.fail(referencedRuleId.equals(ruleEntity.getId()), "不能引用自己");

                        // 防止循环引用
                        ApiAssert.fail(hasCircularReference(ruleEntity.getId(), referencedRuleId, new HashSet<>()), "存在循环引用，无法保存");
                    } catch (NumberFormatException e) {
                        ApiAssert.fail("引用规则ID格式不正确: " + component.getComponentValue());
                    }
                }

                ContractNumberRuleComponentEntity componentEntity = new ContractNumberRuleComponentEntity();
                componentEntity.setRuleId(ruleEntity.getId());
                componentEntity.setComponentType(component.getComponentType());
                componentEntity.setComponentValue(component.getComponentValue());
                componentEntity.setSortOrder(sortOrder++); // 自动生成排序值
                componentEntity.setIsEnabled(true); // 默认启用

                componentEntities.add(componentEntity);
            }

            if (!componentEntities.isEmpty()) {
                boolean componentSaveResult = contractNumberRuleComponentService.saveBatch(componentEntities);
                ApiAssert.fail(!componentSaveResult, "保存合同编号规则组件失败");
            }
        }

        return true;
    }

    @Override
    public List<ContractNumberRuleListVO> getList() {
        // 获取当前用户信息
        UserInfo currentUser = AuthUtil.getCurrentUser();
        ApiAssert.fail(Objects.isNull(currentUser.getEmployeeId()), "当前用户未登录，不允许查询!");

        // 查询所有合同编号规则
        List<ContractNumberRuleEntity> ruleEntities = this.list(new LambdaQueryWrapper<ContractNumberRuleEntity>()
                .orderByAsc(ContractNumberRuleEntity::getCreateTime));

        if (CollectionUtils.isEmpty(ruleEntities)) {
            return new ArrayList<>();
        }

        List<ContractNumberRuleListVO> result = new ArrayList<>();

        for (ContractNumberRuleEntity ruleEntity : ruleEntities) {
            ContractNumberRuleListVO vo = new ContractNumberRuleListVO();
            BeanUtils.copyProperties(ruleEntity, vo);

            // 查询规则对应的组件
            List<ContractNumberRuleComponentEntity> componentEntities = contractNumberRuleComponentService.list(
                    new LambdaQueryWrapper<ContractNumberRuleComponentEntity>()
                            .eq(ContractNumberRuleComponentEntity::getRuleId, ruleEntity.getId())
                            .eq(ContractNumberRuleComponentEntity::getIsEnabled, true)
                            .orderByAsc(ContractNumberRuleComponentEntity::getSortOrder));

            if (!CollectionUtils.isEmpty(componentEntities)) {
                List<ComponentVO> componentVOs = new ArrayList<>();
                for (ContractNumberRuleComponentEntity componentEntity : componentEntities) {
                    ComponentVO componentVO = new ComponentVO();
                    componentVO.setId(componentEntity.getId());
                    componentVO.setComponentType(componentEntity.getComponentType());
                    componentVO.setComponentValue(componentEntity.getComponentValue());
                    componentVO.setSortOrder(componentEntity.getSortOrder());

                    // 如果是引用规则类型，查询引用规则的名称
                    if (ComponentTypeEnums.RULE_REFERENCE.equals(componentEntity.getComponentType())
                            && StringUtils.hasText(componentEntity.getComponentValue())) {
                        try {
                            Long referencedRuleId = Long.parseLong(componentEntity.getComponentValue());
                            ContractNumberRuleEntity referencedRule = this.getById(referencedRuleId);
                            if (referencedRule != null) {
                                componentVO.setReferencedRuleName(referencedRule.getRuleName());
                            }
                        } catch (NumberFormatException e) {
                            // 如果解析失败，忽略
                        }
                    }

                    componentVOs.add(componentVO);
                }
                vo.setComponents(componentVOs);
            } else {
                vo.setComponents(new ArrayList<>());
            }

            result.add(vo);
        }

        return result;
    }

    @Override
    public ContractNumberRuleDetailVO getDetail(Long ruleId) {
        ContractNumberRuleEntity rule = this.getById(ruleId);
        if (null == rule) {
            ApiAssert.fail("合同编号规则不存在");
        }
        ContractNumberRuleDetailVO vo = new ContractNumberRuleDetailVO();

        BeanUtils.copyProperties(rule, vo);

        List<ComponentVO> components = contractNumberRuleComponentService.list(Wrappers.<ContractNumberRuleComponentEntity>lambdaQuery()
                        .eq(ContractNumberRuleComponentEntity::getRuleId, ruleId))
                .stream().map(item -> {
                    ComponentVO componentVO = new ComponentVO();
                    componentVO.setComponentType(item.getComponentType());
                    componentVO.setComponentValue(item.getComponentValue());
                    componentVO.setSortOrder(item.getSortOrder());

                    // 如果是引用规则类型，查询引用规则的名称
                    if (ComponentTypeEnums.RULE_REFERENCE.equals(item.getComponentType())
                            && StringUtils.hasText(item.getComponentValue())) {
                        try {
                            Long referencedRuleId = Long.parseLong(item.getComponentValue());
                            ContractNumberRuleEntity referencedRule = this.getById(referencedRuleId);
                            if (referencedRule != null) {
                                componentVO.setReferencedRuleName(referencedRule.getRuleName());
                            }
                        } catch (NumberFormatException e) {
                            // 如果解析失败，忽略
                        }
                    }

                    return componentVO;
                }).collect(Collectors.toList());
        vo.setComponents(components);
        List<ComponentTypeEnums> enums = ComponentTypeEnums.getComponentsByRuleType(rule.getRuleType());
        List<Map<String, Object>> maps = new ArrayList<>();
        enums.forEach(item -> {
            HashMap<String, Object> map = new HashMap<>();
            map.put("code", item.getCode());
            map.put("msg", item.getMsg());
            if (null != item.getValues()) {
                map.put("values", item.getValues());
            }
            if (item.equals(ComponentTypeEnums.RULE_REFERENCE)) {
                List<Map<String, String>> mapList = this.listReferencedRule(ruleId);
                map.put("values", mapList.stream().map(id -> id.get("id")));
                map.put("referencedRule", mapList);
            }
            maps.add(map);
        });
        vo.setComponent(maps);
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateRule(ContractNumberRuleSaveDTO dto) {
        // 获取当前用户信息
        UserInfo currentUser = AuthUtil.getCurrentUser();
        ApiAssert.fail(Objects.isNull(currentUser.getEmployeeId()), "当前用户未登录，不允许修改!");

        // 参数校验
        ApiAssert.fail(Objects.isNull(dto), "合同编号规则数据不能为空");
        ApiAssert.fail(Objects.isNull(dto.getId()), "规则ID不能为空");
        ApiAssert.fail(!StringUtils.hasText(dto.getRuleName()), "规则名称不能为空");
        ApiAssert.fail(!StringUtils.hasText(dto.getRuleCode()), "规则编码不能为空");
        ApiAssert.fail(Objects.isNull(dto.getRuleType()), "规则类型不能为空");
        ApiAssert.fail(Objects.isNull(dto.getGenerateTiming()), "生成时机不能为空");


        // 检查规则是否存在
        ContractNumberRuleEntity existingRule = this.getById(dto.getId());
        ApiAssert.fail(Objects.isNull(existingRule), "合同编号规则不存在");

        // 检查规则名称是否重复（排除当前记录）
        long nameCount = this.count(new LambdaQueryWrapper<ContractNumberRuleEntity>()
                .eq(ContractNumberRuleEntity::getRuleName, dto.getRuleName())
                .ne(ContractNumberRuleEntity::getId, dto.getId()));
        ApiAssert.fail(nameCount > 0, "规则名称已存在");

        // 检查规则编码是否重复（排除当前记录）
        long codeCount = this.count(new LambdaQueryWrapper<ContractNumberRuleEntity>()
                .eq(ContractNumberRuleEntity::getRuleCode, dto.getRuleCode())
                .ne(ContractNumberRuleEntity::getId, dto.getId()));
        ApiAssert.fail(codeCount > 0, "规则编码已存在");

        // 处理编号模式变更逻辑
        if (NumberModeEnums.SUBJECT_BASED.equals(existingRule.getNumberMode())
                && NumberModeEnums.UNIFIED.equals(dto.getNumberMode())) {
            // 从基于主体模式切换到统一模式时，将所有主体的序号设置为最大值
            syncSequenceNumbersToMax(dto.getId());
        }

        // 更新合同编号规则主表数据
        ContractNumberRuleEntity ruleEntity = new ContractNumberRuleEntity();
        BeanUtils.copyProperties(dto, ruleEntity);

        // 设置自动序号位数
        for (Component component : dto.getComponents()) {
            if (component.getComponentType().equals(ComponentTypeEnums.AUTO_INCREMENT)) {
                ruleEntity.setAutoIncrementDigits(Integer.parseInt(component.getComponentValue()));
            }
        }

        // 保留原有的序号，不重置
        ruleEntity.setCurrentSequence(existingRule.getCurrentSequence());
        if (Objects.isNull(dto.getIsEnabled())) {
            ruleEntity.setIsEnabled(existingRule.getIsEnabled()); // 保持原有启用状态
        }

        // 更新主表数据
        boolean updateResult = this.updateById(ruleEntity);
        ApiAssert.fail(!updateResult, "更新合同编号规则失败");

        // 删除原有的规则组件数据
        boolean deleteResult = contractNumberRuleComponentService.remove(
                new LambdaQueryWrapper<ContractNumberRuleComponentEntity>()
                        .eq(ContractNumberRuleComponentEntity::getRuleId, dto.getId()));

        // 保存新的规则组件数据
        if (!CollectionUtils.isEmpty(dto.getComponents())) {
            List<ContractNumberRuleComponentEntity> componentEntities = new ArrayList<>();
            int sortOrder = 1; // 排序值从1开始自动生成
            for (Component component : dto.getComponents()) {
                if (Objects.isNull(component.getComponentType())) {
                    continue; // 跳过组件类型为空的数据
                }

                // 如果是引用规则类型，验证引用的规则是否存在
                if (ComponentTypeEnums.RULE_REFERENCE.equals(component.getComponentType())
                        && StringUtils.hasText(component.getComponentValue())) {
                    try {
                        Long referencedRuleId = Long.parseLong(component.getComponentValue());
                        ContractNumberRuleEntity referencedRule = this.getById(referencedRuleId);
                        ApiAssert.fail(Objects.isNull(referencedRule), "引用的规则不存在，规则ID: " + referencedRuleId);

                        // 防止自己引用自己
                        ApiAssert.fail(referencedRuleId.equals(dto.getId()), "不能引用自己");

                        // 防止循环引用
                        ApiAssert.fail(hasCircularReference(dto.getId(), referencedRuleId, new HashSet<>()), "存在循环引用，无法保存");
                    } catch (NumberFormatException e) {
                        ApiAssert.fail("引用规则ID格式不正确: " + component.getComponentValue());
                    }
                }

                ContractNumberRuleComponentEntity componentEntity = new ContractNumberRuleComponentEntity();
                componentEntity.setRuleId(dto.getId());
                componentEntity.setComponentType(component.getComponentType());
                componentEntity.setComponentValue(component.getComponentValue());
                componentEntity.setSortOrder(sortOrder++); // 自动生成排序值
                componentEntity.setIsEnabled(true); // 默认启用

                componentEntities.add(componentEntity);
            }

            if (!componentEntities.isEmpty()) {
                boolean componentSaveResult = contractNumberRuleComponentService.saveBatch(componentEntities);
                ApiAssert.fail(!componentSaveResult, "保存合同编号规则组件失败");
            }
        }

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeRule(Long ruleId) {
        // 获取当前用户信息
        UserInfo currentUser = AuthUtil.getCurrentUser();
        ApiAssert.fail(Objects.isNull(currentUser.getEmployeeId()), "当前用户未登录，不允许删除!");

        // 参数校验
        ApiAssert.fail(Objects.isNull(ruleId), "规则ID不能为空");

        // 检查规则是否存在
        ContractNumberRuleEntity existingRule = this.getById(ruleId);
        ApiAssert.fail(Objects.isNull(existingRule), "合同编号规则不存在");

        // 检查是否被其他规则引用
        long referenceCount = contractNumberRuleComponentService.count(
                new LambdaQueryWrapper<ContractNumberRuleComponentEntity>()
                        .eq(ContractNumberRuleComponentEntity::getComponentType, ComponentTypeEnums.RULE_REFERENCE)
                        .eq(ContractNumberRuleComponentEntity::getComponentValue, ruleId.toString())
                        .eq(ContractNumberRuleComponentEntity::getIsEnabled, true));
        ApiAssert.fail(referenceCount > 0, "该规则被其他规则引用，无法删除");

        // 先删除规则组件数据
        contractNumberRuleComponentService.remove(
                new LambdaQueryWrapper<ContractNumberRuleComponentEntity>()
                        .eq(ContractNumberRuleComponentEntity::getRuleId, ruleId));

        // 删除主表数据
        boolean deleteRuleResult = this.removeById(ruleId);
        ApiAssert.fail(!deleteRuleResult, "删除合同编号规则失败");

        return true;
    }

    /**
     * 生成合同编号（带分布式锁）
     *
     * @param dto 生成参数
     * @return 生成的合同编号
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String getContractNumber(GenerateNumberDTO dto) {
        log.info("开始生成合同编号，入参：{}", dto);
        
        // 使用规则类型独立加锁
        String key = RedisKeyConstant.GENERATE_NUMBER_PREFIX + dto.getRuleType().getCode();
        String requestId = UUID.randomUUID().toString(); // 唯一请求标识
        AtomicBoolean isLocked = new AtomicBoolean(false);
        
        log.info("尝试获取分布式锁，key: {}, requestId: {}", key, requestId);
        
        try {
            // 尝试获取锁，设置10秒过期时间
            isLocked.set(tryLock(key, requestId, 10, TimeUnit.SECONDS));
            
            if (!isLocked.get()) {
                // 获取锁失败，进入等待队列
                log.info("获取锁失败，进入等待队列，requestId: {}", requestId);
                
                // 等待获取锁，最多等待10秒
                isLocked.set(waitForLock(key, requestId, 10, TimeUnit.SECONDS));
                
                if (!isLocked.get()) {
                    log.error("获取分布式锁超时，key: {}, requestId: {}", key, requestId);
                    throw new RuntimeException("获取锁失败，防止编号重复");
                }
            }
            
            log.info("成功获取分布式锁，key: {}, requestId: {}", key, requestId);
            
            // 每5秒续期一次
            LOCK_RENEW_POOL.scheduleAtFixedRate(() -> {
                try {
                    renewLock(key, requestId, 5, TimeUnit.SECONDS);
                    log.debug("锁续期成功，key: {}, requestId: {}", key, requestId);
                } catch (Exception e) {
                    log.warn("锁续期失败，key: {}, requestId: {}", key, requestId, e);
                }
            }, 5, 5, TimeUnit.SECONDS);

            // 调用实际生成逻辑
            log.info("开始执行实际编号生成逻辑，requestId: {}", requestId);
            String contractNumber = getContractNumber(dto, new HashSet<>());
            log.info("合同编号生成成功，生成结果：{}, requestId: {}", contractNumber, requestId);
            return contractNumber;
        } catch (Exception e) {
            log.error("生成合同编号失败，dto: {}, requestId: {}", dto, requestId, e);
            return null;
        } finally {
            // 仅当成功获取锁时才尝试释放
            if (isLocked.get()) {
                log.info("开始释放分布式锁，key: {}, requestId: {}", key, requestId);
                // 停止续期任务
                LOCK_RENEW_POOL.shutdown();

                // 释放分布式锁
                releaseLock(key, requestId);
                log.info("分布式锁释放完成，key: {}, requestId: {}", key, requestId);
            }
        }
    }

    /**
     * 尝试获取锁
     */
    private Boolean tryLock(String key, String requestId, long timeout, TimeUnit unit) {
        return redisTemplate.execute(
            (RedisCallback<Boolean>) connection -> connection.set(
                key.getBytes(), 
                requestId.getBytes(), 
                Expiration.from(unit.toMillis(timeout), TimeUnit.MILLISECONDS), 
                RedisStringCommands.SetOption.SET_IF_ABSENT
            )
        );
    }

    /**
     * 等待获取锁
     */
    private boolean waitForLock(String key, String requestId, long timeout, TimeUnit unit) throws InterruptedException {
        long startTime = System.currentTimeMillis();
        long timeoutMillis = unit.toMillis(timeout);
        
        while (System.currentTimeMillis() - startTime < timeoutMillis) {
            // 尝试获取锁
            if (tryLock(key, requestId, 30, TimeUnit.SECONDS)) {
                return true;
            }
            
            // 等待100毫秒后重试
            Thread.sleep(100);
        }
        
        return false;
    }

    /**
     * 续期锁
     */
    private void renewLock(String key, String requestId, long timeout, TimeUnit unit) {
        String renewScript = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                           "return redis.call('expire', KEYS[1], ARGV[2]) " +
                           "else return 0 end";
        
        redisTemplate.execute(
            new DefaultRedisScript<>(renewScript, Long.class),
            Collections.singletonList(key),
            requestId,
            String.valueOf(unit.toSeconds(timeout))
        );
    }

    /**
     * 释放锁
     */
    private void releaseLock(String key, String requestId) {
        String releaseScript = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                               "return redis.call('del', KEYS[1]) " +
                               "else return 0 end";
        
        redisTemplate.execute(
            new DefaultRedisScript<>(releaseScript, Long.class),
            Collections.singletonList(key),
            requestId
        );
    }

    public List<Map<String, String>> listReferencedRule(Long ruleId) {
        return list(new LambdaQueryWrapper<ContractNumberRuleEntity>()
                .eq(ContractNumberRuleEntity::getIsEnabled, true)
                .eq(ContractNumberRuleEntity::getRuleType, RuleTypeEnums.CONTRACT_APPLY)
                .ne(ContractNumberRuleEntity::getId, ruleId)
                .select(ContractNumberRuleEntity::getId, ContractNumberRuleEntity::getRuleName))
                .stream().map(rule -> {
                    Map<String, String> map = new HashMap<>();
                    map.put("id", rule.getId().toString());
                    map.put("ruleName", rule.getRuleName());
                    return map;
                }).collect(Collectors.toList());
    }

    /**
     * 生成合同编号（内部方法，支持循环引用检测）
     *
     * @param dto          生成参数
     * @param visitedRules 已访问的规则ID集合，用于防止循环引用
     * @return 生成的合同编号
     */
    @Transactional(rollbackFor = Exception.class)
    public String getContractNumber(GenerateNumberDTO dto, Set<Long> visitedRules) {
        log.info("进入内部编号生成方法，参数：{}, 已访问规则：{}", dto, visitedRules);
        
        // 参数校验
        ApiAssert.fail(Objects.isNull(dto), "生成编号参数不能为空");
        ApiAssert.fail(Objects.isNull(dto.getLegalId()), "法人ID不能为空");
        ApiAssert.fail(Objects.isNull(dto.getRuleType()), "规则类型不能为空");
        log.info("参数校验通过，法人ID：{}, 规则类型：{}", dto.getLegalId(), dto.getRuleType());

        ContractNumberRuleEntity rule = this.getOne(Wrappers.<ContractNumberRuleEntity>lambdaQuery()
                .eq(ContractNumberRuleEntity::getRuleType, dto.getRuleType())
                .last("limit 1"));
        ApiAssert.fail(Objects.isNull(rule), "合同编号规则不存在");
        ApiAssert.fail(!rule.getIsEnabled(), "合同编号规则已禁用");
        log.info("成功获取编号规则，规则ID：{}, 规则名称：{}, 规则编码：{}", rule.getId(), rule.getRuleName(), rule.getRuleCode());

        // 检查循环引用
        ApiAssert.fail(visitedRules.contains(rule.getId()), "检测到循环引用，无法生成编号");
        visitedRules.add(rule.getId());
        log.info("循环引用检查通过，当前访问规则：{}", visitedRules);

        // 获取法人实体信息
        LegalEntityDetailEntity legalEntity = legalEntityService.getLegalEntityById(dto.getLegalId());
        ApiAssert.fail(Objects.isNull(legalEntity), "法人实体不存在");
        log.info("成功获取法人实体信息，法人名称：{}, 法人简称：{}", legalEntity.getLegalEntityName(), legalEntity.getLegalEntityAbbr());

        // 获取规则组件，按排序顺序
        List<ContractNumberRuleComponentEntity> components = contractNumberRuleComponentService.list(
                new LambdaQueryWrapper<ContractNumberRuleComponentEntity>()
                        .eq(ContractNumberRuleComponentEntity::getRuleId, rule.getId())
                        .eq(ContractNumberRuleComponentEntity::getIsEnabled, true)
                        .orderByAsc(ContractNumberRuleComponentEntity::getSortOrder)
        );

        ApiAssert.fail(CollectionUtils.isEmpty(components), "合同编号规则组件不能为空");
        log.info("成功获取规则组件，组件数量：{}", components.size());

        // 创建生成上下文
        GenerationContext context = new GenerationContext();
        StringBuilder contractNumber = new StringBuilder();
        log.info("开始处理编号组件，初始化生成上下文");

        // 按顺序处理每个组件
        for (int i = 0; i < components.size(); i++) {
            ContractNumberRuleComponentEntity component = components.get(i);
            log.info("处理第{}个组件，组件类型：{}, 组件值：{}, 排序：{}", 
                    i + 1, component.getComponentType(), component.getComponentValue(), component.getSortOrder());
            
            String componentValue = generateComponentValue(component, dto, rule, legalEntity, context, visitedRules);
            if (StringUtils.hasText(componentValue)) {
                contractNumber.append(componentValue);
                log.info("第{}个组件生成成功，生成值：{}, 当前编号：{}", i + 1, componentValue, contractNumber.toString());
            } else {
                log.info("第{}个组件生成为空值，跳过", i + 1);
            }
        }

        String finalContractNumber = contractNumber.toString();
        log.info("编号生成完成，最终编号：{}, 生成上下文：我方主体出现次数{}, 是否已添加我方主体{}", 
                finalContractNumber, context.getOurPartyOccurrenceCount(), context.isOurPartyAdded());
        
        return finalContractNumber;
    }

    /**
     * 生成组件值
     */
    private String generateComponentValue(ContractNumberRuleComponentEntity component,
                                          GenerateNumberDTO dto,
                                          ContractNumberRuleEntity rule,
                                          LegalEntityDetailEntity legalEntity,
                                          GenerationContext context,
                                          Set<Long> visitedRules) {

        ComponentTypeEnums componentType = component.getComponentType();
        String componentValue = component.getComponentValue();
        
        log.info("开始生成组件值，组件类型：{}, 组件值：{}", componentType, componentValue);

        switch (componentType) {
            case FREE_TEXT:
                // 自由文本直接返回
                log.info("处理自由文本组件，返回值：{}", componentValue);
                return componentValue;

            case DATE:
                // 日期格式化
                String formattedDate = formatDate(componentValue);
                log.info("处理日期组件，格式：{}, 生成日期：{}", componentValue, formattedDate);
                return formattedDate;

            case CONTRACT_TYPE:
                // 合同类型编号
                String contractTypeCode = getContractTypeCode(dto.getContractTypeId(), componentValue);
                log.info("处理合同类型组件，合同类型ID：{}, 层级要求：{}, 生成编码：{}", 
                        dto.getContractTypeId(), componentValue, contractTypeCode);
                return contractTypeCode;

            case SEPARATOR:
                // 连接符直接返回
                log.info("处理连接符组件，返回值：{}", componentValue);
                return componentValue;

            case OUR_PARTY:
                // 我方主体简称处理
                String ourPartyResult = handleOurPartyComponent(rule, legalEntity, context);
                log.info("处理我方主体组件，添加模式：{}, 当前出现次数：{}, 是否已添加：{}, 生成值：{}", 
                        rule.getSubjectAddMode(), context.getOurPartyOccurrenceCount(), 
                        context.isOurPartyAdded(), ourPartyResult);
                return ourPartyResult;

            case DOCUMENT_TYPE:
                // 收支类型
                String documentType = StringUtils.hasText(dto.getDocumentType()) ? dto.getDocumentType() : "";
                log.info("处理收支类型组件，收支类型：{}, 生成值：{}", dto.getDocumentType(), documentType);
                return documentType;

            case AUTO_INCREMENT:
                // 自动序号
                String autoIncrementNumber = generateAutoIncrementNumber(rule, dto.getLegalId(), componentValue);
                log.info("处理自动序号组件，规则ID：{}, 法人ID：{}, 位数：{}, 编号模式：{}, 生成序号：{}", 
                        rule.getId(), dto.getLegalId(), componentValue, rule.getNumberMode(), autoIncrementNumber);
                return autoIncrementNumber;

            case RULE_REFERENCE:
                // 引用规则
                /*if (StringUtils.hasText(componentValue)) {
                    try {
                        Long referencedRuleId = Long.parseLong(componentValue);
                        ContractNumberRuleEntity referencedRule = this.getById(referencedRuleId);
                        if (referencedRule != null) {
                            // 创建新的DTO用于引用规则生成
                            GenerateNumberDTO referencedDto = new GenerateNumberDTO();
                            referencedDto.setLegalId(dto.getLegalId());
                            referencedDto.setRuleType(referencedRule.getRuleType());
                            referencedDto.setContractTypeId(dto.getContractTypeId());
                            referencedDto.setDocumentType(dto.getDocumentType());

                            // 递归生成引用规则的编号
                            return getContractNumber(referencedDto, visitedRules);
                        }
                    } catch (NumberFormatException e) {
                        log.warn("无法解析引用规则ID: {}", componentValue);
                    }
                }*/
                String ruleReferenceResult = dto.getContractNumber() == null ? "" : dto.getContractNumber();
                log.info("处理规则引用组件，引用的合同编号：{}", ruleReferenceResult);
                return ruleReferenceResult;

            default:
                log.warn("未知的组件类型：{}, 返回空值", componentType);
                return "";
        }
    }

    /**
     * 处理我方主体组件
     */
    private String handleOurPartyComponent(ContractNumberRuleEntity rule,
                                           LegalEntityDetailEntity legalEntity,
                                           GenerationContext context) {

        context.incrementOurPartyOccurrence();

        SubjectAddModeEnums subjectAddMode = rule.getSubjectAddMode();

        if (SubjectAddModeEnums.FIRST_ONLY.equals(subjectAddMode)) {
            // FIRST_ONLY模式：只在第一次出现时添加
            if (!context.isOurPartyAdded()) {
                context.setOurPartyAdded(true);
                return StringUtils.hasText(legalEntity.getLegalEntityAbbr()) ? legalEntity.getLegalEntityAbbr() : "";
            }
            return "";
        } else if (SubjectAddModeEnums.ALL_PLACES.equals(subjectAddMode)) {
            // ALL_PLACES模式：每次都添加
            return StringUtils.hasText(legalEntity.getLegalEntityAbbr()) ? legalEntity.getLegalEntityAbbr() : "";
        }

        return "";
    }

    /**
     * 生成自动递增序号
     */
    private String generateAutoIncrementNumber(ContractNumberRuleEntity rule, Integer legalId, String digits) {

        int digitCount = 4; // 默认4位
        try {
            if (StringUtils.hasText(digits)) {
                digitCount = Integer.parseInt(digits);
            } else if (rule.getAutoIncrementDigits() != null) {
                digitCount = rule.getAutoIncrementDigits();
            }
        } catch (NumberFormatException e) {
            log.warn("无法解析自动序号位数，使用默认值4位");
        }
        
        log.info("自动序号生成配置，规则ID：{}, 法人ID：{}, 编号模式：{}, 序号位数：{}", 
                rule.getId(), legalId, rule.getNumberMode(), digitCount);

        Integer currentNumber;

        if (NumberModeEnums.UNIFIED.equals(rule.getNumberMode())) {
            // 统一模式：所有主体共用一个序号
            log.info("使用统一编号模式，所有主体共用序号");
            currentNumber = getNextSequenceNumber(rule.getId(), legalId, rule.getNumberMode());
            log.info("获取到序号：{}", currentNumber);

            // 统一模式下，更新所有主体的序号
            log.info("统一模式下，开始更新所有主体的序号到：{}", currentNumber);
            updateAllSubjectSequenceNumbers(rule.getId(), currentNumber);
        } else {
            // 基于主体模式：每个主体独立序号
            log.info("使用基于主体编号模式，主体独立序号");
            currentNumber = getNextSequenceNumber(rule.getId(), legalId, rule.getNumberMode());
            log.info("为主体{}获取到独立序号：{}", legalId, currentNumber);
        }

        // 格式化序号，补足位数
        String formattedNumber = String.format("%0" + digitCount + "d", currentNumber);
        log.info("序号格式化完成，原始序号：{}, 格式化后：{}", currentNumber, formattedNumber);
        return formattedNumber;
    }

    /**
     * 获取合同类型编码
     * 根据传递的类型id进行查询，并判断层级与实际要求的合同类型进行比较
     * 小于要求层级则换为要求层级，大于等于要求层级则使用当前合同简称
     *
     * @param contractTypeId 合同类型ID
     * @param componentValue 要求的层级（"1"=一级类型最粗层级、"2"=二级类型、"3"=三级类型最细层级）
     * @return 合同类型编码
     */
    private String getContractTypeCode(Integer contractTypeId, String componentValue) {
        log.info("开始获取合同类型编码，合同类型ID：{}, 要求层级：{}", contractTypeId, componentValue);
        
        if (contractTypeId == null) {
            log.warn("合同类型ID为空，返回空字符串");
            return "";
        }

        try {
            // 1. 解析要求的层级
            int requiredLevel = 3; // 默认要求层级为3（最细化层级）
            if (StringUtils.hasText(componentValue)) {
                try {
                    requiredLevel = Integer.parseInt(componentValue);
                    if (requiredLevel < 1 || requiredLevel > 3) {
                        requiredLevel = 3; // 如果层级不在有效范围内，默认为3（最细化层级）
                    }
                } catch (NumberFormatException e) {
                    log.warn("无法解析要求层级: {}, 使用默认值3（最细化层级）", componentValue);
                    requiredLevel = 3;
                }
            }
            log.info("解析得到要求层级：{}", requiredLevel);

            // 2. 查询当前合同类型
            ContractTypeEntity currentType = contractTypeMapper.selectById(contractTypeId);
            if (currentType == null) {
                log.warn("合同类型不存在，contractTypeId: {}", contractTypeId);
                return contractTypeId.toString();
            }
            log.info("查询到合同类型信息，类型名称：{}, 类型简称：{}, 父类型ID：{}", 
                    currentType.getTypeName(), currentType.getTypeAbbreviation(), currentType.getParentId());

            // 3. 计算当前合同类型的层级
            int currentLevel = calculateContractTypeLevel(currentType);
            log.info("计算得到当前合同类型层级：{}", currentLevel);

            // 4. 根据层级比较规则获取目标合同类型
            ContractTypeEntity targetType;
            if (currentLevel < requiredLevel) {
                // 当前层级小于要求层级，需要向下查找到要求层级的类型
                log.info("当前层级({})小于要求层级({})，向下查找", currentLevel, requiredLevel);
                targetType = findTypeAtRequiredLevel(currentType, requiredLevel);
                if (targetType == null) {
                    // 如果找不到要求层级的类型，使用当前类型
                    targetType = currentType;
                    log.info("未找到要求层级的类型，使用当前类型");
                } else {
                    log.info("找到要求层级的类型：{}", targetType.getTypeName());
                }
            } else {
                // 当前层级大于等于要求层级，需要向上查找到要求层级的类型
                log.info("当前层级({})大于等于要求层级({})，向上查找", currentLevel, requiredLevel);
                targetType = findParentAtRequiredLevel(currentType, requiredLevel);
                if (targetType == null) {
                    // 如果找不到要求层级的父类型，使用当前类型
                    targetType = currentType;
                    log.info("未找到要求层级的父类型，使用当前类型");
                } else {
                    log.info("找到要求层级的父类型：{}", targetType.getTypeName());
                }
            }

            // 5. 返回目标类型的简称，如果简称为空则返回类型名称
            String result;
            if (StringUtils.hasText(targetType.getTypeAbbreviation())) {
                result = targetType.getTypeAbbreviation();
                log.info("使用类型简称作为编码：{}", result);
            } else {
                result = targetType.getTypeName();
                log.info("类型简称为空，使用类型名称作为编码：{}", result);
            }
            
            return result;

        } catch (Exception e) {
            log.error("获取合同类型编码失败，contractTypeId: {}, componentValue: {}", contractTypeId, componentValue, e);
            return contractTypeId.toString();
        }
    }

    /**
     * 计算合同类型的层级
     *
     * @param contractType 合同类型
     * @return 层级：1-一级类型，2-二级类型，3-三级类型
     */
    private int calculateContractTypeLevel(ContractTypeEntity contractType) {
        if (contractType.getParentId() == null) {
            return 1; // 一级类型
        }

        // 查询父类型
        ContractTypeEntity parentType = contractTypeMapper.selectById(contractType.getParentId());
        if (parentType != null && parentType.getParentId() == null) {
            return 2; // 二级类型
        }

        return 3; // 三级类型
    }

    /**
     * 向上查找到指定层级的父类型
     *
     * @param currentType   当前类型
     * @param requiredLevel 要求的层级
     * @return 指定层级的父类型，如果找不到返回null
     */
    private ContractTypeEntity findParentAtRequiredLevel(ContractTypeEntity currentType, int requiredLevel) {
        ContractTypeEntity searchType = currentType;

        while (searchType != null) {
            int currentLevel = calculateContractTypeLevel(searchType);
            if (currentLevel == requiredLevel) {
                return searchType;
            }

            // 如果已经是一级类型但还没达到要求层级，返回null
            if (searchType.getParentId() == null) {
                break;
            }

            // 查找父类型
            searchType = contractTypeMapper.selectById(searchType.getParentId());
        }

        return null;
    }

    /**
     * 向下查找到指定层级的子类型（如果当前层级小于要求层级）
     * 注意：这个方法用于处理当前层级小于要求层级的情况
     * 实际上在合同编号生成中，通常不会出现这种情况，因为合同类型是确定的
     * 这里保留逻辑完整性，直接返回当前类型
     *
     * @param currentType   当前类型
     * @param requiredLevel 要求的层级
     * @return 当前类型（因为无法确定具体的子类型）
     */
    private ContractTypeEntity findTypeAtRequiredLevel(ContractTypeEntity currentType, int requiredLevel) {
        // 在实际业务中，如果当前层级小于要求层级，说明配置可能有问题
        // 这里直接返回当前类型，避免出错
        log.warn("当前合同类型层级({})小于要求层级({})，使用当前类型: {}",
                calculateContractTypeLevel(currentType), requiredLevel, currentType.getTypeName());
        return currentType;
    }

    /**
     * 获取下一个序号
     */
    private Integer getNextSequenceNumber(Long ruleId, Integer legalId, NumberModeEnums numberMode) {

        log.info("开始获取下一个序号，规则ID：{}, 法人ID：{}, 编号模式：{}", ruleId, legalId, numberMode);
        
        // 查询现有序号记录
        LambdaQueryWrapper<ContractNumberSequenceEntity> queryWrapper = new LambdaQueryWrapper<ContractNumberSequenceEntity>()
                .eq(ContractNumberSequenceEntity::getRuleId, ruleId)
                .eq(ContractNumberSequenceEntity::getLegalId, legalId);

        ContractNumberSequenceEntity sequenceEntity = contractNumberSequenceService.getOne(queryWrapper);

        if (sequenceEntity == null) {
            // 首次生成，创建新记录
            log.info("首次生成序号，创建新记录");
            sequenceEntity = new ContractNumberSequenceEntity();
            sequenceEntity.setRuleId(ruleId);
            sequenceEntity.setLegalId(legalId);
            Integer currentNumber = 0;
            if (NumberModeEnums.UNIFIED.equals(numberMode)) {
                currentNumber = contractNumberSequenceService.list(new LambdaQueryWrapper<ContractNumberSequenceEntity>()
                                .eq(ContractNumberSequenceEntity::getRuleId, ruleId))
                        .stream()
                        .map(ContractNumberSequenceEntity::getCurrentNumber).max(Comparator.comparingInt(item -> item))
                        .orElse(0);
                log.info("统一模式下，查询到当前最大序号：{}", currentNumber);
            }
            sequenceEntity.setCurrentNumber(currentNumber + 1);
            sequenceEntity.setGeneratedDate(new Date());

            contractNumberSequenceService.save(sequenceEntity);
            log.info("新记录保存成功，分配序号：{}", currentNumber + 1);
            return currentNumber + 1;
        } else {
            // 递增序号
            log.info("找到现有序号记录，当前序号：{}", sequenceEntity.getCurrentNumber());
            Integer nextNumber = sequenceEntity.getCurrentNumber() + 1;
            sequenceEntity.setCurrentNumber(nextNumber);
            sequenceEntity.setGeneratedDate(new Date());

            contractNumberSequenceService.updateById(sequenceEntity);
            log.info("序号递增成功，新序号：{}", nextNumber);
            return nextNumber;
        }
    }

    /**
     * 更新所有主体的序号（统一模式使用）
     */
    private void updateAllSubjectSequenceNumbers(Long ruleId, Integer currentNumber) {

        // 查询所有相关的序号记录
        List<ContractNumberSequenceEntity> allSequences = contractNumberSequenceService.list(
                new LambdaQueryWrapper<ContractNumberSequenceEntity>()
                        .eq(ContractNumberSequenceEntity::getRuleId, ruleId));

        // 更新所有记录的序号
        for (ContractNumberSequenceEntity sequence : allSequences) {
            sequence.setCurrentNumber(currentNumber);
            sequence.setGeneratedDate(new Date());
        }

        if (!allSequences.isEmpty()) {
            contractNumberSequenceService.updateBatchById(allSequences);
        }
    }

    /**
     * 同步序号到最大值（从SUBJECT_BASED切换到UNIFIED模式时使用）
     */
    private void syncSequenceNumbersToMax(Long ruleId) {

        // 查询所有相关的序号记录
        List<ContractNumberSequenceEntity> allSequences = contractNumberSequenceService.list(
                new LambdaQueryWrapper<ContractNumberSequenceEntity>()
                        .eq(ContractNumberSequenceEntity::getRuleId, ruleId));

        if (allSequences.isEmpty()) {
            return;
        }

        // 找到最大序号
        Integer maxCurrentNumber = allSequences.stream()
                .mapToInt(ContractNumberSequenceEntity::getCurrentNumber)
                .max()
                .orElse(0);

        // 将所有记录的序号设置为最大值
        for (ContractNumberSequenceEntity sequence : allSequences) {
            sequence.setCurrentNumber(maxCurrentNumber);
            sequence.setGeneratedDate(new Date());
        }

        contractNumberSequenceService.updateBatchById(allSequences);

        log.info("规则ID: {} 的所有主体序号已同步到最大值: {}", ruleId, maxCurrentNumber);
    }


    /**
     * 格式化日期
     */
    private String formatDate(String dateFormat) {
        if (!StringUtils.hasText(dateFormat)) {
            dateFormat = "yyyyMMdd"; // 默认格式
        }

        try {
            SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
            return sdf.format(new Date());
        } catch (Exception e) {
            // 如果格式化失败，返回默认格式
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            return sdf.format(new Date());
        }
    }

    /**
     * 检查是否存在循环引用
     */
    private boolean hasCircularReference(Long currentRuleId, Long targetRuleId, Set<Long> visited) {
        if (currentRuleId.equals(targetRuleId)) {
            return true; // 发现循环
        }

        if (visited.contains(targetRuleId)) {
            return false; // 已经访问过，避免无限递归
        }

        visited.add(targetRuleId);

        // 查询目标规则引用的其他规则
        List<ContractNumberRuleComponentEntity> components = contractNumberRuleComponentService.list(
                new LambdaQueryWrapper<ContractNumberRuleComponentEntity>()
                        .eq(ContractNumberRuleComponentEntity::getRuleId, targetRuleId)
                        .eq(ContractNumberRuleComponentEntity::getComponentType, ComponentTypeEnums.RULE_REFERENCE)
                        .eq(ContractNumberRuleComponentEntity::getIsEnabled, true));

        for (ContractNumberRuleComponentEntity component : components) {
            if (StringUtils.hasText(component.getComponentValue())) {
                try {
                    Long referencedRuleId = Long.parseLong(component.getComponentValue());
                    if (hasCircularReference(currentRuleId, referencedRuleId, visited)) {
                        return true;
                    }
                } catch (NumberFormatException e) {
                    // 忽略格式错误的ID
                }
            }
        }

        visited.remove(targetRuleId); // 回溯时移除
        return false;
    }
}

